﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace GraphicsFramework.Support
{
    class Selections
    {
        private List<Drawing.GraphicBase> selected;
        private Entity.Point2F center;

        public Selections()
        {
            center = new Entity.Point2F();
            selected = new List<Drawing.GraphicBase>();
        }

        public void UpdateSelection(List<Drawing.GraphicBase> selected)
        {
            this.selected.Clear();

            //Update the selections
            foreach (Drawing.GraphicBase drawing in selected)
                this.selected.Add(drawing);

            //Update the selection center
            UpdateCenter();
        }

        private void UpdateCenter()
        {
            if (selected.Count == 0)
                center = new Entity.Point2F(0, 0);
            else if (selected.Count == 1)
                //If there is only one drawing selection, get its center.
                center = selected[0].Center.Clone();
            else
            {
                //Calculate the center base of the boundary of all selected drawings.
                Entity.Rectangle2F bounds = GetOriginalDrawingsBounds();
                center = new Entity.Point2F((bounds.Point1.X + bounds.Point2.X) / 2,
                                            (bounds.Point1.Y + bounds.Point2.Y) / 2);
            }
        }

        public Entity.Rectangle2F GetDrawingsBounds()
        {
            if (selected.Count != 0)
            {
                Entity.Rectangle2F bounds = null;
                Entity.Rectangle2F other = null;

                if (selected.Count == 1)
                {
                    bounds = selected[0].GetBounds();
                }
                else
                {
                    foreach (Drawing.GraphicBase drawing in selected)
                    {
                        //Check if bounds is still null
                        if (bounds != null)
                        {
                            other = drawing.GetBounds();

                            //Check if drawing bound is null.
                            //Merge to the existing bounds if not null.
                            if (other != null)
                                bounds.Merge(other);
                        }
                        else
                        {
                            bounds = drawing.GetBounds();
                        }
                    }
                }

                return bounds;
            }

            return null;
        }

        public Entity.Rectangle2F GetOriginalDrawingsBounds()
        {
            if (selected.Count != 0)
            {
                Entity.Rectangle2F bounds = null;
                Entity.Rectangle2F other = null;

                foreach (Drawing.GraphicBase drawing in selected)
                {
                    //Check if bounds is null
                    if (bounds != null)
                    {
                        other = drawing.GetOriginalBounds();

                        //Check if drawing bound is null.
                        //Merge to the existing bounds if not null.
                        if (other != null)
                            bounds.Merge(other);
                    }
                    else
                    {
                        bounds = drawing.GetOriginalBounds();
                    }
                }

                return bounds;
            }

            return null;
        }

        public void Move(Entity.Point2F move, Entity.Point2F snapvalue)
        {
            foreach (Drawing.GraphicBase drawing in selected)
                drawing.Move(move, snapvalue);

            center.Move(move);
        }

        public void FlipHorizontal()
        {
            foreach (Drawing.GraphicBase drawing in selected)
                    drawing.FlipHorizontal(center);
        }

        public void FlipVertical()
        {
            foreach (Drawing.GraphicBase drawing in selected)
                drawing.FlipVertical(center);
        }

        public void Rotate(float angle, int precision)
        {
            foreach (Drawing.GraphicBase drawing in selected)
                drawing.Rotate(center, angle, precision);
        }

        public void RotateLeft(int precision)
        {
            foreach (Drawing.GraphicBase drawing in selected)
                drawing.RotateLeft(center, precision);
        }

        public void RotateRight(int precision)
        {
            foreach (Drawing.GraphicBase drawing in selected)
                drawing.RotateRight(center, precision);
        }

        public void LeftAlign()
        {
            Entity.Rectangle2F bounds = GetDrawingsBounds();

            if (bounds != null)
            {
                Entity.Rectangle2F local;

                foreach (Drawing.GraphicBase drawing in selected)
                    if (drawing.Selected)
                    {
                        local = drawing.GetBounds();
                        drawing.Move(new Entity.Point2F(bounds.Point1.X - local.Point1.X, 0), new Entity.Point2F(0, 0));
                    }
            }
        }

        public void RightAlign()
        {
            Entity.Rectangle2F bounds = GetDrawingsBounds();

            if (bounds != null)
            {
                Entity.Rectangle2F local;

                foreach (Drawing.GraphicBase drawing in selected)
                    if (drawing.Selected)
                    {
                        local = drawing.GetBounds();
                        drawing.Move(new Entity.Point2F(bounds.Point2.X - local.Point2.X, 0), new Entity.Point2F(0, 0));
                    }
            }
        }

        public void TopAlign()
        {
            Entity.Rectangle2F bounds = GetDrawingsBounds();
            if (bounds != null)
            {
                Entity.Rectangle2F local;

                foreach (Drawing.GraphicBase drawing in selected)
                    if (drawing.Selected)
                    {
                        local = drawing.GetBounds();
                        drawing.Move(new Entity.Point2F(0, bounds.Point2.Y - local.Point2.Y), new Entity.Point2F(0, 0));
                    }
            }
        }

        public void BottomAlign()
        {
            Entity.Rectangle2F bounds = GetDrawingsBounds();
            if (bounds != null)
            {
                Entity.Rectangle2F local;

                foreach (Drawing.GraphicBase drawing in selected)
                    if (drawing.Selected)
                    {
                        local = drawing.GetBounds();
                        drawing.Move(new Entity.Point2F(0, bounds.Point1.Y - local.Point1.Y), new Entity.Point2F(0, 0));
                    }
            }
        }

        public void HorizontalCenterAlign()
        {
            Entity.Rectangle2F bounds = GetDrawingsBounds();

            if (bounds != null)
            {
                Entity.Rectangle2F local;
                Entity.Point2F centerbounds = bounds.GetCenter();
                Entity.Point2F centerlocal;

                foreach (Drawing.GraphicBase drawing in selected)
                    if (drawing.Selected)
                    {
                        local = drawing.GetBounds();
                        centerlocal = local.GetCenter();

                        drawing.Move(new Entity.Point2F(centerbounds.X - centerlocal.X, 0), new Entity.Point2F(0, 0));
                    }
            }
        }

        public void VerticalCenterAlign()
        {
            Entity.Rectangle2F bounds = GetDrawingsBounds();

            if (bounds != null)
            {
                Entity.Rectangle2F local;
                Entity.Point2F centerbounds = bounds.GetCenter();
                Entity.Point2F centerlocal;

                foreach (Drawing.GraphicBase drawing in selected)
                    if (drawing.Selected)
                    {
                        local = drawing.GetBounds();
                        centerlocal = local.GetCenter();

                        drawing.Move(new Entity.Point2F(0, centerbounds.Y - centerlocal.Y), new Entity.Point2F(0, 0));
                    }
            }
        }

        public List<Drawing.GraphicBase> SelectedDrawing
        {
            get { return selected; }
        }

        public Entity.Point2F Center
        {
            get { return center; }
        }

        public int Count
        {
            get { return selected.Count; }
        }

    }
}
